home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / SIRD.ZIP / SIRD.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-06-20  |  43.9 KB  |  1,118 lines

  1. {************************************************}
  2. {                                                }
  3. {   SIRD program                                 }
  4. {                                                }
  5. {   Josef Pöpsel, Dr. Ute Claussen               }
  6. {   for c't, Magazin für Computertechnik         }
  7. {                                                }
  8. {                                                }
  9. {   Please send bug reports to:                  }
  10. {                                                }
  11. {     Josef Pöpsel, Dr. Ute Claussen             }
  12. {     Frohlinder Str. 46                         }
  13. {     44577 Castrop-Rauxel-Schwerin              }
  14. {     Germany                                    }
  15. {     Phone: (+49) 2305 43662                    }
  16. {                                                }
  17. {   Version 1.0                                  }
  18. {   Language: Borland Pascal for Windows V 7.0   }
  19. {                                                }
  20. {   Initial date: Monday, April 27, 1994         }
  21. {   Last changes: Thursday, May 17, 1994         }
  22. {************************************************}
  23.  
  24. {$A+,B-,D-,F-,G+,I-,K+,L-,N+,P-,Q-,R-,S-,T-,V+,W+,X+,Y-}
  25. {$M 8192,8192}
  26.  
  27. program SIRD;
  28.  
  29. {$R SIRD}
  30.  
  31. uses Win31, WinProcs, WinTypes, OWindows, CommDlg, ODialogs, Strings, BWCC;
  32.  
  33. procedure AHIncr; far; external 'KERNEL' index 114;   { "Magic Windows Function whose offset
  34.                                                          is used to increment selectors }
  35.  
  36. const
  37.   HelpFileStr='sird.hlp';   { Filename of HLP-File }
  38.  
  39.   Max_Sird_Size = 2048;     { Change this and DialogBox in SIRD.RES, if needed }
  40.  
  41. { Command IDs }
  42.   cm_LoadDepthPic   = 201;
  43.   cm_LoadTexturePic = 202;
  44.   cm_SaveSIRD       = 203;
  45.   cm_Quit           = 24340;
  46.   cm_SIRDOpts       = 301;
  47.   cm_DoSird         = 401;
  48.   cm_HelpContense   = 501;
  49.   cm_About          = 502;
  50.  
  51. { Dialog IDs }
  52.  
  53.   id_SetEyeDist           = 2001;
  54.   id_SetDPI               = 2002;
  55.   id_UseRandomDots        = 2003;
  56.   id_UseColoredRandomDots = 2004;
  57.   id_UseTexturePicture    = 2005;
  58.   id_SetXRes              = 2006;
  59.   id_SetYRes              = 2007;
  60.   id_SetFixedRatio        = 2008;
  61.   id_AllowMagnification   = 2009;
  62.  
  63.   OneIO  = 32768;  { No. of bytes handled per huge IO operation }
  64.   BMType = $4D42;  { = 'BM', Signature for Windows BMP-Files    }
  65.  
  66.   InchPerMeter=100.0/2.54;
  67.  
  68. type
  69.   PtrRec         = record Lo, Hi: Word end;    { to get from longints to seg:ofs }
  70.   IOFunction     = function(FP: integer; Buf: PChar; Size: Integer): Word;  { function used for hugeIO }
  71.  
  72.   TMyLOGPALETTE = record case boolean of       { TLOGPALETTE with 256 entries }
  73.                     true: ( palVersion: word;
  74.                             palNumEntries: word;
  75.                             palPalEntry: array[0..255] of TPaletteEntry;);
  76.                     false:( org: TLOGPALETTE);
  77.                   end;
  78.  
  79.   TMyBITMAPINFO = record case boolean of     { TBITMAPINFO with 256 entries }
  80.                     true: ( bmiHeader: TBitMapInfoHeader;
  81.                             bmiColors: array[0..255] of TRGBQuad;);
  82.                     false: (org: TBITMAPINFO);
  83.                   end;
  84.   { Type of device independant BitMap: }
  85.   DIBType       = record
  86.                     HasPal       : boolean;        { TRUE, if not True Color }
  87.                     XRes,YRes    : longint;        { Resolution of DIB       }
  88.                     BitMapInfo   : TMyBITMAPINFO;  { Windows Header          }
  89.                     LogPalette   : TMyLOGPALETTE;  { The palette, only valid if HasPal }
  90.                     DIBMemHandle : THANDLE;        { Memory Handle of pixel store }
  91.                     PixMem       : pointer;        { Pointer to pixel store }
  92.                     PalHandle    : HPALETTE;       { Windows handle for palette }
  93.                   end;
  94.  
  95.   { Type of device dependant BitMap, (see DIBType): }
  96.   DDBType       = record
  97.                     HasPal       : boolean;
  98.                     XRes,YRes    : longint;
  99.                     BMPHandle    : HBITMAP;        { Handle of BitMap }
  100.                     PalHandle    : HPALETTE;
  101.                     DC           : HDC;            { Device Context of BitMap }
  102.                     OldObject    : THANDLE;        { Object previously selected in the DC }
  103.                   end;
  104.  
  105.   { Generic Type for RGB and depth maps }
  106.   MapType    = record
  107.                  XRes,YRes   : longint;
  108.                  BaseAdr     : Pointer;  { South-West corner! }
  109.                  BytesPerLine: longint;
  110.                  MemHandle   : THandle;
  111.                end;
  112.  
  113.   DepthType  = MapType;  { Type for Depth Pictures }
  114.   RGBMapType = MapType;  { Type for Texture Picture }
  115.  
  116.   KindType     = (TexW,DepthW,SIRDW,TempW);  { Kind of Window for MDI-Clients }
  117.  
  118.   { Possible coloring of SIRDs: }
  119.   TexToUseType = (UseRandomDots,UseColoredRandomDots,UseTexturePicture);
  120.  
  121.   { Type of array to hold constraints: }
  122.   SameArrType  = array[0..Max_Sird_Size-1] of integer;
  123.  
  124.   { Type of array to hold pixels for one SIRD line: }
  125.   PixArrType   = array[0..Max_Sird_Size-1] of record r,g,b: byte; end;
  126.  
  127. { The Dialog: }
  128.   PSIRDOptDialog = ^TSIRDOptDialog;
  129.   TSIRDOptDialog = object(TDialog)
  130.      constructor Init(AParent: PWindowsObject; AName: pchar);
  131.      procedure HelpReq(var Msg: TMessage);  virtual id_First + idHelp;
  132.   end;
  133.  
  134.  
  135. { derived class for MDI clients: }
  136.   PBMPWnd        = ^TBMPWnd;
  137.   TBMPWnd = object(TWindow)
  138.     TheDDB: DDBType;          { The picture of the Client }
  139.     Kind  : KindType;         { What am I? }
  140.     constructor Init(AParent: PWindowsObject;
  141.                      GeneratingDIB: DIBType; TheKind:KindType; title:pchar);
  142.     procedure Paint(PaintDC: HDC; var PaintInfo: TPaintStruct); virtual;
  143.     procedure GetWindowClass(var WndClass: TWndClass);          virtual;
  144.     procedure WMActivate(var Msg: TMessage);                    virtual wm_First + wm_Activate;
  145.     procedure WMSize(var Msg: TMessage);                        virtual wm_First + wm_Size;
  146.     procedure Redraw(PrecPtr:PRect);
  147.     destructor Done; virtual;
  148.   end;
  149.  
  150. { Main window object: }
  151.   PMainWindow = ^TMainWindow;
  152.   TMainWindow = object(TMDIWindow)
  153.  
  154.     { Variables derived by the dialog box }
  155.     SortOfTexToUse : TexToUseType;   { What kind of SIRD coloring? }
  156.     EyeDist        : single;         { Distance between eyes in DPI }
  157.     DPI            : integer;        { Output resolution in DPI}
  158.     XRes,YRes      : longint;        { Output size in pixel }
  159.     FixedRatio     : boolean;        { XRes/Yres derived by Depth Picture, if TRUE }
  160.     AllowMag       : boolean;        { Texture magnification allowed, if TRUE }
  161.  
  162.  
  163.     HasHelp        : boolean;        { TRUE, if user selected HELP }
  164.  
  165.     { Transfer buffer for Dialog }
  166.     SIRDOpts: record
  167.                  EyeDist        : array[0..15] of char;
  168.                  DPI            : array[0..7] of char;
  169.                  RandomDots,ColoredRandomDots,TexturePicture: word;
  170.                  XRes           : array[0..7] of char;
  171.                  YRes           : array[0..7] of char;
  172.                  FixedRatio     : word;
  173.                  AllowMag       : word;
  174.               end;
  175.  
  176.     SirdBMPWind,TexBMPWind,DepthBMPWind: PBMPWnd;  { Pointer to possible clients }
  177.  
  178.     TheRGBMap: RGBMapType;    { The texture used for coloring the SIRD }
  179.     TheDepth: DepthType;      { Depth information used by the SIRD     }
  180.     TheDepthDIB: DIBType;     { Depth picture as DIB, uses same memory as TheDepth! }
  181.     TheSIRD: DIBType;         { The SIRD as True Color DIB }
  182.     SameArr: SameArrType;     { The array to hold contraints }
  183.     PixArr:  PixArrType;      { The array to hold one scan line of the SIRD }
  184.  
  185.     constructor init(ATitle: PChar; AMenu:HMenu);
  186.     procedure  SetUpWindow; virtual;
  187.     procedure  GetWindowClass(var WndClass: TWndClass); virtual;
  188.     procedure  CMLoadDepth(var Msg: TMessage);          virtual cm_First + cm_LoadDepthPic;
  189.     procedure  CMLoadTex(var Msg: TMessage);            virtual cm_First + cm_LoadTexturePic;
  190.     procedure  CMSaveSIRD(var Msg: TMessage  );         virtual cm_First + cm_SaveSIRD;
  191.     procedure  CMSIRDOpts(var Msg: TMessage);           virtual cm_First + cm_SIRDOpts;
  192.     procedure  CMDoSird(var Msg: TMessage);             virtual cm_First + cm_DoSird;
  193.     procedure  CMHelpContense(var Msg: TMessage);       virtual cm_First + cm_HelpContense;
  194.     procedure  CMAbout(var Msg: TMessage);              virtual cm_First + cm_About;
  195.  
  196.     procedure  AdjustSIRDRes;             { called, if user selects "fixed ratio" }
  197.     function   ConvertDlgInputs: boolean; { converts the dialog transfer buffer to usable vars }
  198.     procedure  SetPercentage(per:single); { Sets window title to show proceed }
  199.     destructor done; virtual;
  200.   end;
  201.  
  202. { Application object }
  203.   TSIRDApp = object(TApplication)
  204.     procedure InitMainWindow; virtual;
  205.   end;
  206.  
  207. var SIRDApp: TSIRDApp;                     { the application }
  208.  
  209. { --------------------------------------- some general functions ------------------------------- }
  210.  
  211. function pchar2str(p:pchar): string;
  212. { converts "C" string to Pascal string }
  213. var s:string;
  214. begin
  215.   s[0]:=char(strlen(p));
  216.   move(p^,s[1],ord(s[0]));
  217.   pchar2str:=s;
  218. end;
  219.  
  220. procedure SetMenuEntry(id:word; mode: word);
  221. { Sets the menue entry id to the mode mode }
  222. var buf:array[0..100] of char;
  223.     h:hMenu;
  224. begin
  225.   h:=GetMenu(SIRDApp.MainWindow^.HWindow);
  226.   GetMenuString(h,id,@buf,100,mf_bycommand);
  227.   ModifyMenu(h,id,mf_bycommand or mode ,id,@buf);
  228.   DrawMenuBar(SIRDApp.MainWindow^.HWindow);
  229. end;
  230.  
  231. { -------------------- some functions to handle big memory arrays: --------------------------- }
  232. procedure __SegIncProc; far; external 'KERNEL' index 114;
  233. var __AddSegInc: LongInt;   (* Additional increment for segments *)
  234.  
  235. procedure incP1(var p: pointer); (* increments p by 1 *)
  236. var newp: longint;
  237. begin
  238.   longint(p):=longint(p)+1;
  239.   if loWord(longint(p))=0 then p:=pointer(longint(p)+__AddSegInc)
  240. end;
  241.  
  242. procedure incP(var p: pointer; toAdd: word); (* increments p by toAdd *)
  243. var newp: longint;
  244. begin
  245.   newp:=longint(p)+toAdd;
  246.   if loWord(newp)<loWord(longint(p)) then p:=pointer(newp+__AddSegInc)
  247.   else p:=pointer(newp);
  248. end;
  249.  
  250. procedure decP(var p: pointer; toSubtract: word); (* decrements p by toAdd *)
  251. var newp: longint;
  252. begin
  253.   newp:=longint(p)-toSubtract;
  254.   if loWord(newp)>loWord(longint(p)) then p:=pointer(newp-__AddSegInc)
  255.   else p:=pointer(newp);
  256. end;
  257.  
  258. function ADDToBase(p: pointer; l:longint): pointer;
  259. { Adds l to the pointer p. p must have the offset 0. }
  260. begin
  261.   ADDToBase:=ptr(ptrrec(p).hi+ PtrRec(l).hi*Ofs(AHIncr),ptrrec(l).lo);
  262. end;
  263.  
  264. { -------------------------------- some file functions: ------------------------------- }
  265.  
  266. function GetFileName(mustexist: boolean; FileMask,Description,FileName:pchar): boolean;
  267. { Gets a filename (FileName) with the Windows 3.1 file dialog box.
  268.   If mustexist=true, the file has to exist beforehand.
  269.   FileMask contains the mask, the file list box uses.
  270.   Description is the text description of the file format, e.g. "Windows BitMap File",
  271.   FileName is the result.
  272.   If FileName is <> NIL, if GetFileName is called, this will be the default FileName. }
  273.  
  274. var OpenFN      : TOpenFileName;
  275.     Filter      : array [0..100] of Char;
  276. begin
  277.   FillChar(Filter, SizeOf(Filter), #0);  { Set up for single null at the end }
  278.   StrCopy(Filter, description);
  279.   StrCopy(@Filter[StrLen(Filter)+1],FileMask);
  280.  
  281.   FillChar(OpenFN, SizeOf(TOpenFileName), #0);
  282.   with OpenFN do begin
  283.     hInstance := 0;   hwndOwner   := SIRDApp.MainWindow^.HWindow;   lpstrDefExt    := '';
  284.     lpstrFile := FileName;  lpstrFilter := Filter; lpstrFileTitle := FileName;
  285.     lStructSize   := sizeof(TOpenFileName);
  286.     nFilterIndex  := 1;
  287.     nMaxFile      := SizeOf(FileName);
  288.     flags     := ofn_HideReadOnly;
  289.     if mustexist then begin
  290.       flags:=flags or ofn_FileMustExist;
  291.       GetFileName:=GetOpenFileName(OpenFN);
  292.     end else begin
  293.       flags:=flags or ofn_OverWritePrompt;
  294.       GetFileName:=GetSaveFileName(OpenFN);
  295.     end;
  296.   end;
  297. end;
  298.  
  299.  
  300. function HugeIO(IOFunc: IOFunction; F: Integer; P: Pointer; Size: Longint): boolean;
  301. { Reads/writes size bytes from/to file F; handles to/from P^ depending on IOFunc.
  302.   Size can be > $FFFF. Returns true, if no error. }
  303. var L, N: Longint;
  304. begin
  305.   HugeIO := true;
  306.   L := 0;
  307.   while L < Size do begin
  308.     N := Size - L;
  309.     if N > OneIO then N := OneIO;
  310.     if IOFunc(F,ADDToBase(p,L),Integer(N))<> N then begin
  311.       HugeIO := false;
  312.       Exit; { abnormal termination }
  313.     end;
  314.     Inc(L, N);
  315.   end;
  316. end;
  317.  
  318. function _LFileSize(F : integer) : longint;
  319. { Gets the file size of file handled by F. File can be larger than $FFFF. }
  320. var CurPos : longint;
  321. begin
  322.   CurPos := _llseek(F,0,1);
  323.   _LFileSize := _llseek(F,0,2);
  324.   _llseek(F,CurPos,0);
  325. end;
  326.  
  327.  
  328.  
  329. { ------------------- some functions for the DIBs and DDBs: ------------------------ }
  330.  
  331. procedure FreeDIB(var TheDIB: DIBType);
  332. { Frees the contents of a DIBType variable }
  333. begin
  334.   GlobalUnlock(TheDIB.DIBMemHandle);
  335.   GlobalFree(TheDIB.DIBMemHandle);
  336.   if TheDIB.HasPal then DeleteObject(TheDIB.PalHandle);
  337. end;
  338.  
  339. procedure FreeRGBMap(var TheRGBMap: RGBMapType);
  340. { Frees the contents of a RGBMapType variable }
  341. begin
  342.   GlobalUnlock(TheRGBMap.MemHandle);
  343.   GlobalFree(TheRGBMap.MemHandle);
  344. end;
  345.  
  346. function LoadBMPAsDIB(var TheDIB: DIBType): boolean;
  347. { Loads a Windows BMP-File into a DIB-Structure after querying the file name.
  348.   Returns true, if user didn┤t press cancel.
  349.   TheDIB.XRes is set to -1, if an error occured during loading.}
  350.  
  351. var fname: pchar;               { Result of file name querying }
  352.     F: Integer;            { File handle for Windows file functions }
  353.     Size: Longint;        { Size of bitmap }
  354.     P: PBitmapInfo;        { Windows bitmap format info header }
  355.     Header: TBitmapFileHeader;  { Bitmap file header }
  356.     i: integer;
  357.     oldCur: HCursor;
  358. begin
  359.   LoadBMPAsDIB:=FALSE;
  360.   TheDIB.XRes:=-1;
  361.   GetMem(fname,255); StrCopy(fname,'*.BMP');
  362.   if GetFileName(TRUE,'*.BMP','Windows BitMap File',fname) then with TheDib do begin
  363.     LoadBMPAsDIB:=TRUE;                               { user didn┤t press cancel }
  364.     OldCur:=SetCursor(LoadCursor(0, idc_Wait));
  365.     F := _LOpen(fname, of_Read);
  366.     if F = -1 then Exit;
  367.     FreeMem(fname,255);
  368.     if (_LRead(F, @Header, SizeOf(Header)) <> SizeOf(Header)) or (Header.bfType <> BMType) then begin
  369.       _LClose(F);  SetCursor(OldCur); Exit;
  370.     end;
  371.     Size := _LFileSize(F) - SizeOf(TBitmapFileHeader);
  372.     DIBMemHandle := GlobalAlloc(gmem_Moveable, Size);
  373.     if DIBMemHandle = 0 then begin _LClose(F); SetCursor(OldCur); Exit; end;
  374.     P := GlobalLock(DIBMemHandle);
  375.     PixMem:=AddToBase(P,Header.bfOffBits - SizeOf(TBitmapFileHeader));
  376.     if HugeIO(_LRead, F, P, Size) and
  377.      (P^.bmiHeader.biSize = SizeOf(TBitmapInfoHeader)) then begin
  378.       Size:=Header.bfOffBits - SizeOf(TBitmapFileHeader);
  379.       if Size>sizeof(TMyBITMAPINFO) then Size:=sizeof(TMyBITMAPINFO);
  380.       move(P^,BitMapInfo,Size);
  381.       XRes:=BitMapInfo.bmiHeader.biWidth;
  382.       YRes:=BitMapInfo.bmiHeader.biHeight;
  383.       if BitMapInfo.bmiHeader.biBitCount<>24 then begin
  384.         HasPal:=TRUE;
  385.         LogPalette.PalVersion:=$300;
  386.         LogPalette.PalNumEntries:=BitMapInfo.bmiHeader.biClrUsed;
  387.         if LogPalette.PalNumEntries=0 then LogPalette.PalNumEntries:=1 shl BitMapInfo.bmiHeader.biBitCount;
  388.         for i:=0 to LogPalette.PalNumEntries-1 do begin
  389.           with BitMapInfo.bmiColors[i], LogPalette.PalPalEntry[i] do begin
  390.             peRed:=rgbRed;
  391.             peGreen:=rgbGreen;
  392.             peBlue:=rgbBlue;
  393.             peFlags:=0;
  394.           end;
  395.         end;
  396.         PalHandle:=CreatePalette(LogPalette.org);
  397.       end else HasPal:=FALSE;
  398.     end else begin
  399.       GlobalUnlock(DIBMemHandle); GlobalFree(DIBMemHandle);
  400.       _LClose(F); SetCursor(OldCur); Exit;
  401.     end;
  402.     _LClose(F);
  403.     SetCursor(OldCur);
  404.   end else FreeMem(fname,255);
  405. end;
  406.  
  407.  
  408. function DDBToRGBMap(TheDDB: DDBType; var TheRGBMap: RGBMapType): boolean;
  409. { Converts a device dependent BitMap to a RGBMapType variable (converts to TrueColor).
  410.   Returns TURE, if successful. }
  411.  
  412. var BytesNeeded: longint;   { TheRGBMap pixels }
  413.     bmi:TBitMapInfo;        { header of internal TrueColor DIB }
  414.     DC:HDC;                 { device context to build the TrueColor DIB }
  415.     oldCur: HCursor;
  416. begin
  417.   DDBToRGBMap:=FALSE;
  418.   OldCur:=SetCursor(LoadCursor(0, idc_Wait));
  419.   with TheRGBMap do begin
  420.     XRes:=TheDDB.XRes;
  421.     YRes:=TheDDB.YRes;
  422.     BytesPerLine:=(XRes*3+3) and not 3;   (* bytes per line must be a multiple of 4 *)
  423.     BytesNeeded:=BytesPerLine * YRes;
  424.     MemHandle:=GlobalAlloc(gmem_Moveable, BytesNeeded);
  425.     if MemHandle<>0 then BaseAdr := GlobalLock(MemHandle) else exit;
  426.     with bmi.bmiHeader do begin             (* set up the header to get the bits *)
  427.       biSize:=sizeof(TBitMapInfoHeader);
  428.       biWidth:=XRes;          biHeight:=YRes;
  429.       biPlanes:=1;            biBitCount:=24;
  430.       biCompression:=BI_RGB;  biSizeImage:=BytesNeeded;
  431.       biXPelsPerMeter := 0;   biYPelsPerMeter := 0;
  432.       biClrUsed       := 0;   biClrImportant  := 0;
  433.     end;
  434.     DC:=GetDC(0);
  435.     if TheDDB.HasPal then begin            { Select palette, if the DDB has one }
  436.       SelectPalette(DC,TheDDB.PalHandle,false);
  437.       RealizePalette(DC);
  438.     end;
  439.     GetDIBits(DC,TheDDB.BMPHandle,0,YRes,BaseAdr,bmi,DIB_RGB_COLORS);  (* get the bits *)
  440.     ReleaseDC(0,DC);
  441.   end;
  442.   DDBToRGBMap:=TRUE;
  443.   SetCursor(OldCur);
  444. end;
  445.  
  446. function RGBMapToDepthBuf(TheRGBMap: RGBMapType; var TheDepth: DepthType): boolean;
  447. { Converts a RGBMapType structure to a DepthType structure by calcualting the
  448.   intensity of every pixel. Returns TRUE, if successful. }
  449. var BytesNeeded: longint;
  450.     oldCur: HCursor;
  451.     ps,pd: pointer;
  452.     x,y,r,g,b: integer;
  453. begin
  454.   RGBMapToDepthBuf:=FALSE;
  455.   OldCur:=SetCursor(LoadCursor(0, idc_Wait));
  456.   with TheDepth do begin
  457.     XRes:=TheRGBMap.XRes;
  458.     YRes:=TheRGBMap.YRes;
  459.     BytesPerLine:=(XRes+3) and not 3;   (* one byte/pixel, bytes per line must be a multiple of 4 *)
  460.     BytesNeeded:=BytesPerLine * YRes;
  461.     MemHandle:=GlobalAlloc(gmem_Moveable, BytesNeeded);
  462.     if MemHandle<>0 then BaseAdr := GlobalLock(MemHandle) else exit;
  463.     for y:=0 to YRes-1 do begin  (* For every scan line: *)
  464.       { Get address of leftmost pixel in source and destination: }
  465.       ps:=AddToBase(TheRGBMap.BaseAdr,y*TheRGBMap.BytesPerLine);
  466.       pd:=AddToBase(TheDepth.BaseAdr,y*TheDepth.BytesPerLine);
  467.       { Convert every pixel of the scan: }
  468.       for x:=0 to XRes-1 do begin
  469.         r:=byte(ps^); incP1(ps);  { Order of color components in DIB-mem is r,g,b }
  470.         g:=byte(ps^); incP1(ps);
  471.         b:=byte(ps^); incP1(ps);
  472.         byte(pd^):=hi(r*130+g*97+b*28);   (* Intensity of color (0.51*r+0.38*g+0.11*b) *)
  473.         incP1(pd);
  474.       end;
  475.     end;
  476.   end;
  477.   RGBMapToDepthBuf:=TRUE;
  478. end;
  479.  
  480. procedure DepthBufToDIB(TheDepth: DepthType; var TheDIB: DIBType);
  481. { Converts TheDepth to 8 bit color index DIB with gray scale palette.
  482.   Attention: TheDIB uses the same pixel store as TheDepth does. }
  483. var i: integer;
  484. begin
  485.   with TheDib do begin
  486.     HasPal:=TRUE;
  487.     XRes:=TheDepth.XRes;
  488.     YRes:=TheDepth.YRes;
  489.     PixMem:=TheDepth.BaseAdr;
  490.     DIBMemHandle:=TheDepth.MemHandle;
  491.     with BitMapInfo.bmiHeader do begin   (* Fill up the DIB's header *)
  492.       biSize:=sizeof(TBitMapInfoHeader);
  493.       biWidth:=XRes;          biHeight:=YRes;
  494.       biPlanes:=1;            biBitCount:=8;
  495.       biCompression:=BI_RGB;  biSizeImage:=TheDepth.BytesPerLine*YRes;
  496.       biXPelsPerMeter := 0;   biYPelsPerMeter := 0;
  497.       biClrUsed       := 0;   biClrImportant  := 0;
  498.     end;
  499.     (* Construct grayscale palette for 8 Bit DIBs: *)
  500.     with LogPalette do begin
  501.       PalVersion:=$300; PalNumEntries:=256;
  502.       for i:=0 to 255 do with PalPalEntry[i],BitMapInfo.bmiColors[i] do begin
  503.         peRed:=i; peGreen:=i; peBlue:=i; peFlags:=0;
  504.         rgbBlue:=i; rgbGreen:=i; rgbRed:=i; rgbReserved:=0;
  505.       end;
  506.     end;
  507.     PalHandle:=CreatePalette(LogPalette.org);
  508.   end;
  509. end;
  510.  
  511. function DIBToDDB(TheDIB: DIBType; var TheDDB: DDBType): boolean;
  512. { Creates a DC and a DDB (derived from TheDIB) which then is selected for that DC.
  513.   Returnes true, if successful. }
  514. var GotDC: HDC;               { Device context of the screen }
  515.     oldCur: HCursor;
  516. begin
  517.   GotDC:=GetDC(0);
  518.   TheDDB.DC:=CreateCompatibleDC(GotDC);
  519.   OldCur:=SetCursor(LoadCursor(0, idc_Wait));
  520.   if TheDIB.HasPal then begin
  521.     TheDDB.PalHandle:=CreatePalette(TheDIB.LogPalette.org);
  522.     SelectPalette(GotDC,TheDDB.PalHandle,false);
  523.     RealizePalette(GotDC);
  524.   end;
  525.   TheDDB.BMPHandle:= CreateDIBitmap(GotDC,TheDIB.BitMapInfo.bmiHeader,cbm_Init,
  526.                                     TheDIB.PixMem,TheDIB.BitMapInfo.org, dib_RGB_Colors);
  527.   TheDDB.OldObject:=SelectObject(TheDDB.DC,TheDDB.BMPHandle);
  528.   ReleaseDC(0,GotDC);
  529.   TheDDB.HasPal:=TheDib.HasPal;
  530.   TheDDB.XRes:=TheDIB.XRes;
  531.   TheDDB.YRes:=TheDIB.YRes;
  532.   SetCursor(OldCur);
  533. end;
  534.  
  535. { ----------------------------------- Methods of TBMPWnd -----------------------------------------}
  536. constructor TBMPWnd.Init(AParent: PWindowsObject; GeneratingDIB: DIBType;
  537.                          TheKind: KindType; title: pchar);
  538. { Creates a MDI child of kind TheKind which displays the pixels of GeneratingDIB
  539.   as a DDB. The window title is set to title. }
  540. begin
  541.   inherited Init(AParent,title);
  542.   Kind:=TheKind;
  543.   DibToDDB(GeneratingDIB,TheDDB); { Create the DDB }
  544.   attr.w:=TheDDB.XRes+30; attr.h:=TheDDB.YRes+30;
  545.   Attr.Style := Attr.Style or ws_VScroll or ws_HScroll;
  546.   Scroller := New(PScroller, Init(@Self, 1, 1, 200, 200));
  547.   Scroller^.AutoMode:=false;
  548. end;
  549.  
  550. procedure TBMPWnd.GetWindowClass(var WndClass: TWndClass);
  551. (* Get the Icon we want. *)
  552. begin
  553.   inherited GetWindowClass(WndClass);
  554.   WndClass.hIcon := LoadIcon(HInstance, 'SIRDIcon');
  555. end;
  556.  
  557. procedure TBMPWnd.WMSize(var Msg: TMessage);
  558. (* Sets scroller and limits the window┤s size to the maximum size of the
  559.    containing BitMap *)
  560. const SIZE_MAXIMIZED=2; (* has been forgotten to be defined in Win..*)
  561. var Rc,Rw:TRect; wc,hc,ww,hw:integer; pnt:TPoint;
  562. begin
  563.   inherited WMSize(Msg);
  564.   GetClientRect(HWindow,Rc);
  565.   GetWindowRect(HWindow,Rw);
  566.   wc:=rc.right-rc.left; hc:=rc.bottom-rc.top;
  567.   ww:=rw.right-rw.left; hw:=rw.bottom-rw.top;
  568.   if wc>TheDDB.XRes then ww:=ww-wc+TheDDB.XRes ;
  569.   if hc>TheDDB.YRes  then hw:=hw-hc+TheDDB.YRes ;
  570.   Scroller^.SetRange(TheDDB.XRes -wc,TheDDB.YRes -hc);
  571.   if Msg.wParam<>SIZE_MAXIMIZED then begin (* if it must be, ok! *)
  572.     GetClientRect(HWindow,Rc);
  573.     GetWindowRect(HWindow,Rw);
  574.     pnt.x:=Rw.left; pnt.y:=Rw.top;
  575.     ScreenToClient(SIRDApp.MainWindow^.HWindow,pnt);
  576.     wc:=rc.right-rc.left; hc:=rc.bottom-rc.top;
  577.     ww:=rw.right-rw.left; hw:=rw.bottom-rw.top;
  578.     if wc>TheDDB.XRes  then ww:=ww-wc+TheDDB.XRes ;
  579.     if hc>TheDDB.YRes  then hw:=hw-hc+TheDDB.YRes ;
  580.     MoveWindow(HWindow,pnt.x,pnt.y,ww,hw,true);
  581.   end;
  582. end;
  583.  
  584. procedure TBMPWnd.Redraw(PRecPtr:PRect);
  585. { Redraws an MDI-Child. If PRecPtr=Nil, the window is redrawn completely, otherwise only
  586.   the PRecPtr^portion is redrawn. }
  587. var DC:HDC;
  588.     xs,ys,xd,yd:integer;
  589. begin
  590.   DC:=GetDC(HWindow);
  591.   if PRecPtr<>NIL then with PRecPtr^ do
  592.     BitBlt(DC,left,top,right-left,bottom-top,TheDDB.DC,           (* redraw only a part   *)
  593.               left+Scroller^.XPos,top+Scroller^.YPos,SRCCOPY)
  594.   else                                                        (* redraw it completely *)
  595.     BitBlt(DC,-Scroller^.XPos,-Scroller^.YPos,TheDDB.XRes,TheDDB.YRes,TheDDB.DC,0,0,SRCCOPY);
  596.   ReleaseDC(HWindow,DC);
  597. end;
  598.  
  599.  
  600. procedure TBMPWnd.Paint(PaintDC: HDC; var PaintInfo: TPaintStruct);
  601. (* Redraws the needed part of the actual window *)
  602. begin
  603.   Redraw(@PaintInfo.rcPaint);
  604. end;
  605.  
  606. procedure TBMPWnd.WMActivate(var Msg: TMessage);
  607. (* If the window's bitmap has a palette, set it! *)
  608. var DC: HDC;
  609. begin
  610.   if TheDDB.HasPal then begin
  611.     DC:=GetDC(HWindow);
  612.     SelectPalette(DC,TheDDB.PalHandle,false);
  613.     RealizePalette(DC);
  614.     ReleaseDC(HWindow,DC);
  615.   end;
  616.   inherited WMActivate(Msg);
  617. end;
  618.  
  619. destructor TBMPWnd.done;
  620. { Deletes an MDI client and frees its pixels. The parent┤s pointer to the
  621.   corresponding MID clients are set to NIL. }
  622. begin
  623.   { The next line is a workaround for a bug in the program, or a bug
  624.     in the OWL of Borland. If a MDI client with scrollers is maximized and
  625.     its destructor is called, the program crashes. If anybody knows
  626.     why, please contact us! Address see at the top of this program. }
  627.   if IsZoomed(HWindow) then PMDIWindow(Parent)^.CascadeChildren;
  628.   SelectObject(TheDDB.DC,TheDDB.OldObject);
  629.   DeleteObject(TheDDB.BMPHandle);
  630.   if TheDDB.HasPal then DeleteObject(TheDDB.PalHandle);
  631.   DeleteDC(TheDDB.DC);
  632.   case Kind of
  633.     TexW   : begin
  634.                PMainWindow(Parent)^.TexBMPWind:=NIL;
  635.                FreeRGBMap(PMainWindow(Parent)^.TheRGBMap);
  636.              end;
  637.     DepthW : begin
  638.                PMainWindow(Parent)^.DepthBMPWind:=NIL;
  639.                FreeDIB(PMainWindow(Parent)^.TheDepthDIB);
  640.                SetMenuEntry(cm_DoSird,mf_grayed);
  641.              end;
  642.     SirdW  : begin
  643.                PMainWindow(Parent)^.SIRDBMPWind:=NIL;
  644.                FreeDIB(PMainWindow(Parent)^.TheSIRD);
  645.                SetMenuEntry(cm_SaveSird,mf_grayed);
  646.              end;
  647.  
  648.   end;
  649.   inherited done;
  650. end;
  651.  
  652.  
  653. { ------------------------ Methods for the dialog boxes ---------------------------------- }
  654. constructor TSIRDOptDialog.Init(AParent: PWindowsObject; AName: pchar);
  655. { Set up transfer buffers for dialog }
  656. var dummy: pointer;
  657. begin
  658.   inherited Init(AParent,AName);
  659.   dummy:=New(PEdit,InitResource(@Self,id_SetEyeDist,16));
  660.   dummy:=New(PEdit,InitResource(@Self,id_SetDPI,8));
  661.   dummy:=New(PRadioButton,InitResource(@Self,id_UseRandomDots));
  662.   dummy:=New(PRadioButton,InitResource(@Self,id_UseColoredRandomDots));
  663.   dummy:=New(PRadioButton,InitResource(@Self,id_UseTexturePicture));
  664.   dummy:=New(PEdit,InitResource(@Self,id_SetXRes,8));
  665.   dummy:=New(PEdit,InitResource(@Self,id_SetYRes,8));
  666.   dummy:=New(PCheckBox,InitResource(@Self,id_SetFixedRatio));
  667.   dummy:=New(PCheckBox,InitResource(@Self,id_AllowMagnification));
  668. end;
  669.  
  670. procedure TSIRDOptDialog.HelpReq;
  671. { Called, if the help button of the dialog is pressed }
  672. begin
  673.   if WinHelp(hWindow,HelpFileStr,HELP_CONTEXT,100) then
  674.     PMainWindow(SIRDApp.MainWindow)^.HasHelp:=TRUE;
  675. end;
  676.  
  677. { ----------------------------------- Methods of TMainWindow -----------------------------}
  678. constructor TMainWindow.Init(ATitle: PChar; AMenu: HMenu);
  679. (* Initializes main window, sets size to complete screen *)
  680. var r: TRect;
  681. begin
  682.   inherited init(ATitle,AMenu);
  683.   GetClientRect(GetDesktopWindow,r);
  684.   attr.x:=r.left; attr.y:=r.top; attr.w:=r.right-r.left; attr.h:=r.bottom-r.top;
  685. end;
  686.  
  687. procedure TMainWindow.SetUpWindow;
  688. (* Set up "global" variables *)
  689. var HDC:THandle;
  690.     dummy:integer;
  691. begin
  692.   inherited SetUpWindow;
  693.   TexBMPWind:=NIL;
  694.   DepthBMPWind:=NIL;
  695.   SIRDBMPWind:=NIL;
  696.   HasHelp:=FALSE;
  697.   with SIRDOpts do begin
  698.     RandomDots:=bf_checked; ColoredRandomDots:=0; TexturePicture:=0;
  699.     wvsprintf(DPI,'72',dummy);
  700.     wvsprintf(EyeDist,'2.5',dummy);
  701.     wvsprintf(XRes,'640',dummy);
  702.     wvsprintf(YRes,'480',dummy);
  703.     FixedRatio:=bf_checked;
  704.     AllowMag:=0;
  705.   end;
  706.   ConvertDlgInputs;  (* Initializes the variables used by the
  707.                         corresponding transfer buffers *)
  708.   HDC:=GetDC(HWindow);
  709.   if GetDeviceCaps(HDC,BITSPIXEL)<15 then
  710.     messagebox(0,'You are running Windows in color index mode so '+
  711.                  'that the display quality of SIRD is not optimal in all cases.'+
  712.                  'Try to run Windows in true color mode (>=32k colors).',
  713.                  'SIRD', MB_TASKMODAL or MB_ICONINFORMATION or MB_OK);
  714.   ReleaseDC(HWindow,HDC);
  715. end;
  716.  
  717. procedure TMainWindow.GetWindowClass(var WndClass: TWndClass);
  718. { Display the Icon we want! }
  719. begin
  720.   inherited GetWindowClass(WndClass);
  721.   WndClass.hIcon := LoadIcon(HInstance, 'SIRDIcon');
  722. end;
  723.  
  724. procedure TMainWindow.AdjustSIRDRes;
  725. { If fixed ratio is checked, the smaller of XRes and YRes is set to a value
  726.   so that the ratio is identical to that of the depth picture. }
  727. var ratio: single; s: string;
  728. begin
  729.   if (DepthBMPWind<>NIL) and FixedRatio then begin
  730.     ratio:=TheDepth.XRes/TheDepth.YRes;
  731.     if XRes>YRes then YRes:=round(XRes/ratio) else XRes:=round(YRes*ratio);
  732.     str(XRes,s); s:=s+#0; move(s[1],SIRDOpts.XRes,length(s));
  733.     str(YRes,s); s:=s+#0; move(s[1],SIRDOpts.YRes,length(s));
  734.   end;
  735. end;
  736.  
  737.  
  738. procedure TMainWindow.CMLoadDepth(var Msg: TMessage);
  739. { Loads a depth image and diplays it }
  740. var TheDIB: DIBType;
  741.     DepthColBMPWind:PBMPWnd;
  742.     MyRGBMap: RGBMapType;
  743. begin
  744.   if LoadBMPAsDIB(TheDIB) then begin
  745.     if not TheDib.XRes=-1 then messagebox(HWindow,'Error loading BitMap',
  746.                                           'SIRD', MB_TASKMODAL or MB_ICONEXCLAMATION or MB_OK)
  747.     else begin
  748.       if DepthBMPWind<>NIL then DepthBMPWind^.Done; { Delete the old, if it exists }
  749.       { Display the loaded picture: }
  750.       DepthColBMPWind:=PBMPWnd(SirdApp.MakeWindow(New(PBMPWnd,Init(@Self,TheDib,TempW,'Color-Depth'))));
  751.       DepthColBMPWind^.Redraw(NIL);                     { We want to see it now!        }
  752.       FreeDib(TheDib);                                  { Not needed any longer         }
  753.       DDBToRGBMap(DepthColBMPWind^.TheDDB,MyRGBMap);    { Convert the DDB to a RGB-Map  }
  754.       RGBMapToDepthBuf(MyRGBMap,TheDepth);              { Convert RGB-Map to Depth-Map  }
  755.       FreeRGBMap(MyRGBMap);                             { Not needed any longer         }
  756.       DepthBufToDIB(TheDepth,TheDepthDIB);              { Convert Depth to DIB          }
  757.       DepthColBMPWind^.Done;                            { We don┤t want it any more     }
  758.       { Display the depth picture (a gray level version of the loaded picture): }
  759.       DepthBMPWind:=PBMPWnd(SirdApp.MakeWindow(New(PBMPWnd,Init(@Self,TheDepthDib,DepthW,'Depth'))));
  760.       XRes:=TheDepth.Xres; YRes:=TheDepth.Yres;
  761.       AdjustSIRDRes;                       { Now we have a ratio which can be adjusted  }
  762.       SetMenuEntry(cm_DoSird,0);           { Depth is loaded, so we can calculate SIRDS }
  763.     end;
  764.   end;
  765. end;
  766.  
  767. procedure TMainWindow.CMLoadTex(var Msg: TMessage);
  768. { Loads a texture and displays it in an MDI window }
  769. var TheDIB: DIBType;  { Temp. store for the texture }
  770. begin
  771.   if LoadBMPAsDIB(TheDIB) then begin  { Load one }
  772.     if not TheDib.XRes=-1 then  messagebox(HWindow,'Error loading BitMap',
  773.                                           'SIRD', MB_TASKMODAL or MB_ICONEXCLAMATION or MB_OK)
  774.     else begin
  775.       if TexBMPWind<>NIL then TexBMPWind^.Done; { If old exists, free it }
  776.       { Make a new MDI window: }
  777.       TexBMPWind:=PBMPWnd(SirdApp.MakeWindow(New(PBMPWnd,Init(@Self,TheDib,TexW,'Texture'))));
  778.       { Convert its DDB to a RGB-Map: }
  779.       DDBToRGBMap(TexBMPWind^.TheDDB,TheRGBMap);
  780.       FreeDib(TheDib);  { We don┤t need the DIB any more, because we use TheRGBMap }
  781.     end;
  782.   end;
  783. end;
  784.  
  785. procedure TMainWindow.CMAbout(var Msg: TMessage);
  786. { Advertising is a MUST ... }
  787. begin
  788.   Application^.ExecDialog(New(PDialog, Init(@Self, 'AboutDialog')));
  789. end;
  790.  
  791. procedure TMainWindow.CMHelpContense(var Msg: TMessage);
  792. { Help is wanted }
  793. begin
  794.   if WinHelp(hWindow,HelpFileStr,HELP_CONTENTS,0)then
  795.     PMainWindow(SIRDApp.MainWindow)^.HasHelp:=TRUE;
  796. end;
  797.  
  798. procedure TMainWindow.CMSIRDOpts(var Msg: TMessage);
  799. { Displays the dialog box as long as no input error occurs.
  800.   Converts the transfer buffer to usable variables by calling ConvertDlgInputs }
  801. var TheDialog: PSIRDOptDialog;
  802. begin
  803.   repeat
  804.     TheDialog:=New(PSirdOptDialog, Init(@Self, 'SIRDOptionDialog'));
  805.     TheDialog^.TransferBuffer:=@SirdOpts;
  806.     Application^.ExecDialog(TheDialog);
  807.   until ConvertDlgInputs;
  808. end;
  809.  
  810.  
  811. function TMainWindow.ConvertDlgInputs: boolean;
  812. (* Converts the dialog transfer buffer to "normal" variables *)
  813. var s:string;
  814.     err:integer;
  815.     f:file;
  816. begin
  817.   if SIRDOpts.RandomDots=bf_checked then SortOfTexToUse:=UseRandomDots
  818.   else if SIRDOpts.ColoredRandomDots=bf_checked  then SortOfTexToUse:=UseColoredRandomDots
  819.   else if SIRDOpts.TexturePicture=bf_checked  then SortOfTexToUse:=UseTexturePicture;
  820.   val(pchar2str(SIRDOpts.DPI),DPI,err);
  821.   if err=0 then val(pchar2str(SIRDOpts.EyeDist),EyeDist,err);
  822.   if err=0 then val(pchar2str(SIRDOpts.XRes),XRes,err);
  823.   if err=0 then val(pchar2str(SIRDOpts.YRes),YRes,err);
  824.  
  825.   if DPI<20 then err:=1; if DPI>3000 then err:=1;
  826.   if EyeDist<1.0 then err:=1; if EyeDist>5.0 then err:=1;
  827.   if XRes<100 then err:=1; if XRes>Max_Sird_Size then err:=1;
  828.   if YRes<100 then err:=1; if YRes>Max_Sird_Size then err:=1;
  829.   FixedRatio:=SIRDOpts.FixedRatio=bf_checked;
  830.   AllowMag:=SIRDOpts.AllowMag=bf_checked;
  831.   AdjustSIRDRes;
  832.   ConvertDlgInputs:=err=0;
  833. end;
  834.  
  835. procedure TMainWindow.SetPercentage(per:single);
  836. (* Sets the window title to "SIRD  per%". IF per is less than 0,
  837.    the window title is set to "SIRD". *)
  838. var buf:string;
  839.     peri:integer;
  840. const oldper:integer=-1;
  841. begin
  842.   peri:=round(per);
  843.   if peri<>oldper then begin
  844.     if peri<0 then buf:='SIRD'+#0
  845.     else begin
  846.       str(peri:3,buf);
  847.       buf:='SIRD ('+buf+'%)'+#0;
  848.     end;
  849.     SetWindowText(HWindow,@Buf[1]);
  850.     oldper:=peri;
  851.   end;
  852. end;
  853.  
  854.  
  855. procedure MakeSameArr(pDepth: pointer; xDepthStep: single; Cnt: integer;
  856.                       EyeDist: single; Resolution: integer;
  857.                       var SameArr: SameArrType);
  858. {
  859.   Calculation of constraints for one scan line in the SIRD output.
  860.  
  861.   pDepth     points to the memory with the depth information for this
  862.              line (one byte per pixel, 0 is far away, 255 is nearby)
  863.  
  864.   xDepthStep is the step size to do in the depth buffer for one step
  865.              in the SIRD line. This variable is needed, because the
  866.              depth picture resolution and the SIRD-Resolution don┤t
  867.              have to be the same.
  868.  
  869.   Cnt        is the number of Pixels in one SIRD output line.
  870.  
  871.   EyeDist    is the distance of the eyes in Inch.
  872.  
  873.   Resolution is the output resolution of the SIRD in DPI.
  874.  
  875.   SameArr    holds the Result of the procedure. It┤s funct6ionality
  876.              is explained in the text.
  877. }
  878.  
  879. const zScal=1.0/255.0;    { Depth scaling factor                       }
  880.       mu   =1.0/3.0;      { Distance of the near plane to the far      }
  881.  
  882. var   x         : integer;{ Position in the SIRD line                  }
  883.       xdo,xd    : integer;{ old, actual position in the depth buffer   }
  884.       depx      : single; { real actual position in depth buffer       }
  885.       p,ph      : pointer;{ pointers into depth buffer                 }
  886.       Z         : single; { normalized depth buffer value at x         }
  887.       Zorg      : integer;{ unnormalized depth buffer value at x       }
  888.       E         : single; { Eyes distance [in pixels of the SIRD]      }
  889.       left,right: integer;{ separated projections of the actual pixels }
  890.       s         : integer;{ separation [in pixels of the SIRD]         }
  891.       visible   : boolean;{ true, if both eyes can see the point       }
  892.       t,ts,zt   : integer;{ used for hidden surface removal            }
  893.       ft        : single; { used for hidden surface removal            }
  894.       l         : integer;{ value of SameArr[left], see text           }
  895.  
  896. begin
  897.   for x:=0 to Cnt-1 do SameArr[x]:=x; { All values are "unconstrained" }
  898.   E:=round(EyeDist*Resolution);       { EyeDist [in pixels of the SIRD]}
  899.   ft:=2/(zScal*mu*E);                 { Factor for hidden surface      }
  900.   depx:=0; xdo:=0; xd:=0; p:=pDepth;  { Set up step variables and ptr. }
  901.   for x:=0 to Cnt-1 do begin          { for all x of the SIRD line:    }
  902.     Zorg:=byte(p^);                   { Get the depth                  }
  903.     Z:=zorg * zScal;                  { Scale it to 0.0..1.0           }
  904.     s:=round((1.0-mu*Z)*E/(2.0-mu*Z));      { Calculate separation     }
  905.     left:=x-s div 2; right:=left+s;         { this would be seen       }
  906.     if (0<=left) and (right<Cnt) then begin { if both are in the SIRD: }
  907.       t:=1;               { test x+-t, whether it hides x, start at t=1}
  908.       repeat
  909.         zt:=Zorg+round((2-mu*z)*t*ft); { the biggest z allowed (0..255)}
  910.         ts:=round(t*xDepthStep);       { transform t into  depth buffer}
  911.         ph:=p; decP(ph,ts);            { get depth pixel at x-t        }
  912.         visible:=byte(ph^)<zt;         { is it hiding the pixel at x?  }
  913.         if visible then begin          { no? May be the one at x+t does}
  914.           ph:=p; incP(ph,ts);          { get depth pixel at x+t        }
  915.           visible:=byte(ph^)<zt;       { is it hiding the pixel at x?  }
  916.         end;
  917.         inc(t);                          { For the next time           }
  918.       until (not visible) or (zt>255); { until hidden or in front of }
  919.       if visible then begin              { if seen from both eyes:     }
  920.         l:=SameArr[left];                         { set up l, see text }
  921.         while (l<>left) and (l<>right) do begin   { ---- see text ---- }
  922.           if (l<right) then begin                 { ---- see text ---- }
  923.             left:=l; l:=SameArr[left];            { ---- see text ---- }
  924.           end else begin                          { ---- see text ---- }
  925.             SameArr[left]:=right; left:=right;    { ---- see text ---- }
  926.             l:=SameArr[left]; right:=l;           { ---- see text ---- }
  927.           end;                                    { ---- see text ---- }
  928.         end;                                      { ---- see text ---- }
  929.         SameArr[left]:=right;                     { Set the constraint }
  930.       end;
  931.     end;
  932.     depx:=depx+xDepthStep;       { Do a real step for the depth buffer }
  933.     xd:=round(depx);             { This is the integer coordinate of it}
  934.     incP(p,xd-xdo);              { Get the next depth address          }
  935.     xdo:=xd;                     { For the next address-increment      }
  936.   end;
  937. end;
  938.  
  939.  
  940. procedure TMainWindow.CMDoSIRD(var Msg: TMessage);
  941. { Calculate the complete SIRD }
  942. var BytesNeeded,BytesPerLine: longint;
  943.     oldCur: HCursor;
  944.     ThisSortOfTex: TexToUseType;
  945.     y:integer;
  946.     pSird,pS,pDepth,pDeptho,pTex: pointer;
  947.     DepthXStep,DepthYStep: single;
  948.     x: integer;
  949.     MaxSep: integer;
  950.     xtex,ytex:integer;
  951.     texstep:single;
  952. begin
  953.   if SIRDBMPWind<>NIL then SIRDBMPWind^.Done;
  954.   if TexBMPWind<>Nil then TexBMPWind^.Redraw(Nil);
  955.   if DepthBMPWind<>Nil then DepthBMPWind^.Redraw(Nil);
  956.   ThisSortOfTex:=SortOfTexToUse;
  957.   if (ThisSortOfTex=UseTexturePicture) and (TexBMPWind=Nil) then begin
  958.     messagebox(HWindow,'Texture enabled but not loaded, choose one!',
  959.                        'SIRD', MB_TASKMODAL or MB_ICONEXCLAMATION or MB_OK);
  960.     ThisSortOfTex:=UseRandomDots;
  961.   end;
  962.   OldCur:=SetCursor(LoadCursor(0, idc_Wait));
  963.   (* Generate DIB for the SIRD: *)
  964.   BytesPerLine:=(XRes*3+3) and not 3;
  965.   BytesNeeded:=BytesPerLine * YRes;
  966.   TheSIRD.XRes:=XRes;
  967.   TheSIRD.YRes:=YRes;
  968.   with TheSIRD do begin
  969.     HasPal:=FALSE;
  970.     DIBMemHandle:=GlobalAlloc(gmem_Moveable, BytesNeeded);
  971.     if DIBMemHandle<>0 then PixMem := GlobalLock(DIBMemHandle) else exit;
  972.     with BitMapInfo.bmiHeader do begin
  973.       biSize:=sizeof(TBitMapInfoHeader);
  974.       biWidth:=XRes;          biHeight:=YRes;
  975.       biPlanes:=1;            biBitCount:=24;
  976.       biCompression:=BI_RGB;  biSizeImage:=BytesNeeded;
  977.       biXPelsPerMeter := round(DPI*InchPerMeter);
  978.       biYPelsPerMeter := biXPelsPerMeter;
  979.       biClrUsed       := 0;   biClrImportant  := 0;
  980.     end;
  981.   end;
  982.   (* Set up pointers for depth buffer and SIRD image *)
  983.   pSird:=TheSIRD.PixMem;
  984.   pDepth:=TheDepth.BaseAdr;
  985.   pDeptho:=NIL;
  986.   DepthXStep:=(TheDepth.XRes-1)/(XRes-1); (* Steps for depth buffer   *)
  987.   DepthYStep:=(TheDepth.YRes-1)/(YRes-1);
  988.   MaxSep:=round(EyeDist*DPI*0.5);      (* Separation for far plane    *)
  989.   for y:=0 to YRes-1 do begin          (* for all scans in SIRD:      *)
  990.     SetPercentage(y/yRes*100);         (* show process                *)
  991.     if pDepth<>pDeptho then            (* did we step in y for depth? *)
  992.       (* Calculate the constraints: *)
  993.       MakeSameArr(pDepth,DepthXStep,XRes,EyeDist,DPI,SameArr);
  994.     pDeptho:=pDepth;                             (* for the next scan *)
  995.     if ThisSortOfTex=UseRandomDots then begin    (* black & white RDs *)
  996.       for x:=XRes-1 downto 0 do begin
  997.         if SameArr[x]=x then with PixArr[x] do begin  (* free choice? *)
  998.           r:=lo(255+random(2)); g:=r; b:=r;
  999.         end else PixArr[x]:=PixArr[SameArr[x]];
  1000.       end;
  1001.     end else if ThisSortOfTex=UseColoredRandomDots then begin
  1002.       for x:=XRes-1 downto 0 do begin
  1003.         if SameArr[x]=x then with PixArr[x] do begin
  1004.           r:=random(255);
  1005.           g:=random(255);
  1006.           b:=random(255);
  1007.         end else PixArr[x]:=PixArr[SameArr[x]];
  1008.       end;
  1009.     end else begin
  1010.       texstep:=TheRGBMap.XRes/MaxSep;             (* step in texture  *)
  1011.       if not AllowMag then if texstep<1.0 then texstep:=1.0;
  1012.  
  1013.       ytex:=round(y*texstep) mod TheRGBMap.YRes;        (* y in texture *)
  1014.       for x:=XRes-1 downto 0 do begin
  1015.         if SameArr[x]=x then with PixArr[x] do begin    (* free choice? *)
  1016.           xtex:=round(x*texstep) mod TheRGBMap.XRes;    (* x in texture *)
  1017.           pTex:=AddToBase(TheRGBMap.BaseAdr,TheRGBMap.BytesPerLine*yTex+xTex*3);
  1018.           (* Copy the pixel: *)
  1019.           b:=byte(pTex^); incP1(pTex);
  1020.           g:=byte(pTex^); incP1(pTex);
  1021.           r:=byte(pTex^);
  1022.         end else PixArr[x]:=PixArr[SameArr[x]];        (* constrained *)
  1023.       end;
  1024.     end;
  1025.  
  1026.     (* copy Pixels of PixArr to SIRD-DIB: *)
  1027.     pS:=pSird;
  1028.     for x:=0 to XRes-1 do with PixArr[x] do begin
  1029.       byte(ps^):=b; incP1(ps);
  1030.       byte(ps^):=g; incP1(ps);
  1031.       byte(ps^):=r; incP1(ps);
  1032.     end;
  1033.     (* Increment pointers to SIRD and depth buffer: *)
  1034.     incP(pSird,BytesPerLine);
  1035.     pDepth:=AddToBase(TheDepth.BaseAdr,round(y*DepthYStep)*TheDepth.BytesPerLine);
  1036.   end;
  1037.  
  1038.   SetPercentage(-1);
  1039.   (* Show the DIB: *)
  1040.   SIRDBMPWind:=PBMPWnd(SirdApp.MakeWindow(New(PBMPWnd,Init(@Self,TheSIRD,SirdW,'SIRD-Output'))));
  1041.   (* Enable saving: *)
  1042.   SetMenuEntry(cm_SaveSird,0);
  1043.   SetCursor(OldCur);
  1044. end;
  1045.  
  1046. procedure TMainWindow.CMSaveSIRD(var Msg: TMessage);
  1047. (* Saves the Pixels of the SIRD in a 24 bit BMP-File *)
  1048. var fname: pchar;
  1049.     F: Integer;            { File Handle for Windows file functions }
  1050.     Header: TBitmapFileHeader;  { Bitmap file header }
  1051.     oldCur: HCursor;
  1052.     BytesNeeded: longint;
  1053.     OfStruct:TOfStruct;
  1054.  
  1055. label Error;
  1056.  
  1057. begin
  1058.   GetMem(fname,255); StrCopy(fname,'*.BMP');
  1059.   if GetFileName(FALSE,'*.BMP','Windows BitMap File',fname) then with TheSIRD do begin
  1060.     OldCur:=SetCursor(LoadCursor(0, idc_Wait));
  1061.     F := OpenFile(fname, OfStruct, of_create);
  1062.     if F = -1 then goto Error;
  1063.     BytesNeeded := ((XRes*3+3) and not 3) * YRes;
  1064.     with Header do begin
  1065.       bfType:=BMType;
  1066.       bfOffBits:=SizeOf(Header)+SizeOf(TheSIRD.BitMapInfo.org);
  1067.       bfSize:=bfOffBits+BytesNeeded;
  1068.       bfReserved1:=0;
  1069.       bfReserved2:=0;
  1070.     end;
  1071.     if _LWrite(F, @Header, SizeOf(Header)) <> SizeOf(Header) then begin
  1072.       _LClose(F); goto Error;
  1073.     end;
  1074.     if _LWrite(F, @TheSIRD.BitMapInfo.org, SizeOf(TheSIRD.BitMapInfo.org)) <>
  1075.                                            SizeOf(TheSIRD.BitMapInfo.org) then begin
  1076.       _LClose(F); goto Error;
  1077.     end;
  1078.  
  1079.     if not HugeIO(_LWrite, F, PixMem, BytesNeeded) then begin
  1080.       _LClose(F); goto Error;
  1081.     end;
  1082.  
  1083.     _LClose(F);
  1084.     SetCursor(OldCur);
  1085.   end;
  1086.   FreeMem(fname,255);
  1087.   exit;
  1088. Error:
  1089.   FreeMem(fname,255);
  1090.   SetCursor(OldCur);
  1091.   messagebox(HWindow,'Error saving BitMap','SIRD', MB_TASKMODAL or MB_ICONEXCLAMATION or MB_OK)
  1092. end;
  1093.  
  1094.  
  1095. destructor TMainWindow.done;
  1096. (* Close the Help-Window, if opened: *)
  1097. begin
  1098.   if HasHelp then WinHelp(hWindow,HelpFileStr,HELP_QUIT,0);
  1099.   inherited done;
  1100. end;
  1101.  
  1102. { ----------------------------------- Methods of TSIRDApp -----------------------------------------}
  1103.  
  1104. procedure TSIRDApp.InitMainWindow;
  1105. { Create the application's main window. }
  1106. begin
  1107.   MainWindow := New(PMainWindow, Init('SIRD',LoadMenu(HInstance, 'MainMenu')));
  1108. end;
  1109.  
  1110.  
  1111. begin
  1112.   __AddSegInc:=ofs(__SegIncProc);
  1113.   __AddSegInc:=(__AddSegInc-1) shl 16; (* Correction of segments, if offset overflow *)
  1114.   SIRDApp.Init('SIRD');
  1115.   SIRDApp.Run;
  1116.   SIRDApp.Done;
  1117. end.
  1118.